package com.kylin.common.paginate;


import java.util.List;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.ScrollableResults;
import org.hibernate.criterion.Projections;

/**
 * Hibernate分页信息
 */
public class HibernatePage implements Page {
    
    private List elements = new Vector();
    private int pageSize;
    private int pageNumber;
    private int totalElementsCount = 0;
    
    private Logger logger = Logger.getLogger(HibernatePage.class);
    
    public HibernatePage(){
        this.pageNumber = 1;
        this.pageSize = 10;
    }
    
    public HibernatePage(int pageNumber, int pageSize){
        this.pageNumber = pageNumber;
        this.pageSize = pageSize;
    }
    
    public HibernatePage(int pageNumber, int pageSize ,int totalElementsCount){
        this.pageNumber = pageNumber;
        this.pageSize = pageSize;
        this.totalElementsCount = totalElementsCount;
    }
    
    //我又加上了
  public HibernatePage(Query query, int pageNumber, int pageSize) {
        this.pageNumber = pageNumber;
        this.pageSize = pageSize;
        try {
            ScrollableResults scrollableResults = query.scroll();
            //get the total elements number
            scrollableResults.last();
            this.totalElementsCount = scrollableResults.getRowNumber() + 1;
            if (Integer.MAX_VALUE == this.pageNumber || this.pageNumber > getLastPageNumber())   //last page
            {
                this.pageNumber = getLastPageNumber();
            }
            elements =
                    query.setFirstResult((this.pageNumber - 1) * this.pageSize).setMaxResults(
                            this.pageSize)
                    .list();
        } catch (HibernateException e) {
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 构建HibernatePage对象，完成Hibernate的Query数据的分页处理
     *
     * @param queryCount 用于查询总记录数的Query对象
     * @param query   Hibernate的Query对象
     * @param pageNumber 当前页编码，从1开始，如果传的值为Integer.MAX_VALUE表示获取最后一页。
     *                   如果你不知道最后一页编码，传Integer.MAX_VALUE即可。如果当前页超过总页数，也表示最后一页。
     *                   这两种情况将重新更改当前页的页码，为最后一页编码。
     * @param pageSize   每一页显示的条目数
     */
    public HibernatePage(Query queryCount,Query query, int pageNumber, int pageSize) {
        this.pageNumber = pageNumber;
        this.pageSize = pageSize;
        try {
            //get the total elements number
            this.totalElementsCount = ((Integer)queryCount.uniqueResult()).intValue();
            if(logger.isDebugEnabled()) logger.debug("total elements: " + totalElementsCount);
            if (Integer.MAX_VALUE == this.pageNumber || this.pageNumber > getLastPageNumber())   //last page
            {
                this.pageNumber = getLastPageNumber();
            }
            elements =
                    query.setFirstResult((this.pageNumber - 1) * this.pageSize).setMaxResults(
                            this.pageSize)
                            .list();
        } catch (HibernateException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 构建HibernatePage对象，完成Hibernate的Query数据的分页处理
     *
     * @param criteria   Hibernate的Criteria对象
     * @param pageNumber 当前页编码，从1开始，如果传的值为Integer.MAX_VALUE表示获取最后一页。
     *                   如果你不知道最后一页编码，传Integer.MAX_VALUE即可。如果当前页超过总页数，也表示最后一页。
     *                   这两种情况将重新更改当前页的页码，为最后一页编码。
     * @param pageSize   每一页显示的条目数
     */
    public HibernatePage(Criteria criteria, int pageNumber, int pageSize) {
        this.pageNumber = pageNumber;
        this.pageSize = pageSize;
        try {
            //ScrollableResults scrollableResults = criteria.scroll();
            //scrollableResults.last();
            //this.totalElementsCount = scrollableResults.getRowNumber() + 1;
            //get the total elements number
            criteria.setProjection(Projections.rowCount());
            totalElementsCount = ((Integer)criteria.uniqueResult()).intValue();
            criteria.setProjection(null);
            if(logger.isDebugEnabled()) logger.debug("total elements: " + totalElementsCount);
            if (Integer.MAX_VALUE == this.pageNumber ||
                    this.pageNumber > getLastPageNumber())   //last page
            {
                this.pageNumber = getLastPageNumber();
            }
            elements =
                    criteria.setFirstResult((this.pageNumber - 1) * this.pageSize)
                            .setMaxResults(this.pageSize).list();
        } catch (HibernateException e) {
            throw new RuntimeException(e);
        }
    }
    public boolean isFirstPage() {
        return getPageNumber() == 1;
    }
    public boolean isLastPage() {
        return getPageNumber() >= getLastPageNumber();
    }
    public boolean hasNextPage() {
        return getLastPageNumber() > getPageNumber();
    }
    public boolean hasPreviousPage() {
        return getPageNumber() > 1;
    }
    public int getLastPageNumber() {
        return totalElementsCount % this.pageSize == 0 ?
                totalElementsCount / this.pageSize : totalElementsCount / this.pageSize + 1;
    }
    /**
     * 返回List类型数据
     *
     * @return List数据源
     */
    public List getElements() {
        return elements;
    }
    public int getTotalElementsCount() {
        return totalElementsCount;
    }
    public int getFirstElementNumber() {
        return (getPageNumber() - 1) * getPageSize() + 1;
    }
    public int getLastElementNumber() {
        int fullPage = getFirstElementNumber() + getPageSize() - 1;
        return getTotalElementsCount() < fullPage ? getTotalElementsCount() : fullPage;
    }
    public int getNextPageNumber() {
        return getPageNumber() + 1;
    }
    public int getPreviousPageNumber() {
        return getPageNumber() - 1;
    }
    public int getPageSize() {
        return pageSize;
    }
    public int getPageNumber() {
        return pageNumber;
    }
    /**
     * @param elements The elements to set.
     */
    public void setElements(List elements) {
        this.elements = elements;
    }
    
    /**
     * 得到当前页的第一条记录在整个结果中的number
     * @return
     */
    public int getCurrentPageFirstResultNumber(){
        return (this.pageNumber-1)*this.pageSize -1;
    }
    
    public String toString(){
        return "Page:[pageNo]=" + this.pageNumber +
                ",[pageSize]=" + this.pageSize + 
                ",[totalCount]=" + this.getTotalElementsCount();
    }
    /**
     * @param totalElementsCount The totalElementsCount to set.
     */
    public void setTotalElementsCount(int totalElementsCount) {
        this.totalElementsCount = totalElementsCount;
    }
}
